package net.esj.basic.core.engine.util;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.esj.basic.plugins.struts2.dispatcher.PerfMultiPartRequest;
import net.esj.basic.utils.DateUtils;
import net.esj.basic.utils.StringUtils;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUpload;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang.RandomStringUtils;

public abstract class FileUploadUtils {

	private static final String UPLOAD_PERCENT_COUNTER = "_SES_UP_PER_COUNTER";
	
	public static final String[] upload(HttpServletRequest request,HttpServletResponse response,String savePath,boolean randomName) throws Exception{
		
		FileUploadListener listener = new FileUploadListener(request.getSession());
		
		DiskFileItemFactory fac = new DiskFileItemFactory();
		ServletFileUpload upload = new ServletFileUpload(fac);
		upload.setProgressListener(listener);
		upload.setHeaderEncoding("utf-8");
		List fileList = null;
		fileList = upload.parseRequest(request);
		
		List<String> reval = new ArrayList<String>();
		
		
		Iterator<FileItem> it = fileList.iterator();
		
		String name = "";
		String extName = "";
		String pathStr = "";
		while (it.hasNext()) {
			FileItem item = it.next();
			if (!item.isFormField()) {
				name = item.getName();
				long size = item.getSize();
				String type = item.getContentType();
//				System.out.println(size+"字节" + " " + type);
				//路径
				String[] pathArr = item.getFieldName().split("/");
				String pathName = pathArr[pathArr.length-1];
				pathStr += "/";
				File f1 = new File(savePath);
				if (!f1.exists()) {
					f1.mkdirs();
				}
				
				if (name == null || name.trim().equals("")) {
					continue;
				}
				String fileName  = name;
				if(randomName){
					fileName = randomFileName(name);
				}
				File saveFile = new File(savePath +File.separator+ fileName);
				item.write(saveFile);
				reval.add(fileName);
			}
		}
		request.getSession().removeAttribute(UPLOAD_PERCENT_COUNTER);
		return reval.toArray(new String[0]);
	}
	
	public static final double getUploadPercent(HttpServletRequest request){
		Double d = (Double) request.getSession().getAttribute(PerfMultiPartRequest.UPLOAD_PERCENT_COUNTER);
		if(d!=null){
			return d.doubleValue();
		}
		return -1;
	}
	
	private static final java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat(
			"yyyyMMddHHmmss");
	private static String randomFileName(String realFilename){
		StringBuilder sb = new StringBuilder();
		String post = ".ml";
		if(realFilename.lastIndexOf(".")>0){
			post = realFilename.substring(realFilename.lastIndexOf("."));
		}
		sb.append(formatter.format(DateUtils.now()));
		sb.append(RandomStringUtils.random(6, StringUtils.getN36Chars())).append(post);
		return sb.toString();
	}

	private static class HttpServletRequestProxy extends HttpServletRequestWrapper{

		private UploadFileObserver observer;
		
		public HttpServletRequestProxy(HttpServletRequest request,UploadFileObserver observer) {
			super(request);
			this.observer = observer;
		}

		@Override
		public ServletInputStream getInputStream() throws IOException {
			ServletInputStream in =  super.getInputStream();
			return new ServletInputStreamProxy(in, observer);
		}
		
	}
	
	private static class ServletInputStreamProxy extends ServletInputStream{
		
		private ServletInputStream in;
		private UploadFileObserver observer;
		
		public ServletInputStreamProxy(ServletInputStream in,
				UploadFileObserver observer) {
			super();
			this.in = in;
			this.observer = observer;
		}

		public int read(byte[] b,int off,int len) throws IOException {
			int r=in.read(b, off, len);
			if(r!=-1){
				observer.makeUploadSize(r);
			}
			return r;
		}

		@Override
		public int read() throws IOException {
			return in.read();
		}
		
		
	}
	
	private static class FileUploadListener implements ProgressListener{
		
		private HttpSession session;
		
		public FileUploadListener(HttpSession session) {
			super();
			this.session = session;
		}

		@Override
		public void update(long arg0, long arg1, int arg2) {
			session.setAttribute(UPLOAD_PERCENT_COUNTER, (arg0/(arg1*1.0))*100.0);
		}
		
	}
	
	private static class UploadFileObserver{
		
		private long receivedSize = 0;
		
		private long totalSize;
		
		private HttpSession session;
		
		public UploadFileObserver(HttpSession session) {
			super();
			this.session = session;
		}

		public void setTotalSize(long totalSize) {
			this.totalSize = totalSize;
		}

		public void makeUploadSize(int r){
			receivedSize+= r;
			session.setAttribute(UPLOAD_PERCENT_COUNTER, calcPercent());
		}
		
		public double calcPercent(){
			return ((receivedSize/(totalSize*1.0))*100);
		}
	}
}
